package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.itheima.model.domain.UserInfo;
import com.itheima.model.mongo.Movement;
import com.itheima.model.mongo.Visitors;
import com.itheima.model.tanhua.sso.vo.ErrorResult;
import com.itheima.model.vo.MovementsVo;
import com.itheima.model.vo.PageResult;
import com.itheima.model.vo.VisitorsVo;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.template.OssTemplate;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {
    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 发布动态
     */
    @PostMapping
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws Exception {
        //判断动态的内容是否存在
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }
        //2.获取当前的登录的用户id
        Long userId = UserHolder.getUserId();
        //3.将当前文件上传到阿里云oss，获取请求地址
        ArrayList<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }
        //4、将数据封装到Movement对象
        movement.setUserId(userId);
        movement.setMedias(medias);
        //5.调用api完成发布动态
        movementApi.pushlish(movement);
    }

    /**
     * 查询个人动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //1、根据用户id，调用api查询个人动态内容(PageResult -- Movement)
        PageResult pr = movementApi.findByUserId(userId, page, pagesize);
        //2、获取pageResult中的item对象
        List<Movement> items = (List<Movement>) pr.getItems();
        //3、非空判断
        if (items != null) {
            return pr;
        }
        //4、循环列表数据
        UserInfo userInfo = userInfoApi.findById(userId);
        ArrayList<MovementsVo> vo = new ArrayList<>();
        for (Movement item : items) {
            //5、一个movement构建一个vo对象
            MovementsVo init = MovementsVo.init(userInfo, item);
            vo.add(init);
        }
        //6、构建返回值
        pr.setItems(vo);
        return pr;
    }

    //好友动态
    public PageResult findFriendMovement(Integer page, Integer pageSize) {
        //获取当前id
        Long userId = UserHolder.getUserId();
        //2查询数据列表
        List<Movement> friendMovement = movementApi.findFriendMovement(page, pageSize, userId);
        //3、判断列表是否为空
        return getPageResult(page, pageSize, friendMovement);
    }

    //抽取公共方法
    public PageResult getPageResult(Integer page, Integer pageSize, List<Movement> friendMovement) {
        if (CollUtil.isEmpty(friendMovement)){
            return new PageResult();
        }
        //4.提取动态发布人的id列表
        List<Long> userId = CollUtil.getFieldValues(friendMovement, "userId", Long.class);
        //5、根据用户的id列表获取动态详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(userId, null);
        //6、一个movement构建一个vo对象
        ArrayList<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : friendMovement) {
            UserInfo userInfo = map.get(movement.getUserId());
            if (userInfo != null){
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                //修复点赞状态bug，判断hashKey是否存在
                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key,hashKey)){
                    vo.setHasLiked(1);
                }
                vos.add(vo);
            }
        }
        return new PageResult(page, pageSize, 0L, vos);
    }

    //查询推荐动态
    public PageResult findRecommendMovements(Integer page, Integer pageSize) {
        //1、从redis中获取推荐数据
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //2、判断推荐数据是否存在
        List<Movement> list = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)) {
            //3、如果不存在，调用api随即构造10条动态数据
            list = movementApi.randomMovements(pageSize);
        } else {
            //4、如果存在，处理pid数据
            String[] values = redisValue.split(",");
            //判断当前页起始条数是否小于数组总数
            if ((page - 1) * pageSize < values.length) {
                List<Long> pids = Arrays.stream(values).skip((page - 1) * pageSize).limit(pageSize)
                        .map( e -> Long.valueOf(e))
                        .collect(Collectors.toList());
                //5、调用api数组查询动态数据
                list = movementApi.findMovementByPids(pids);
            }
        }
        //6、调用公共方法调用返回值
        return getPageResult(page, pageSize, list);
    }

    /**
     * 根据动态id查询动态详情
     * @param movementId
     * @return
     */
    public MovementsVo findOneMovement(String movementId) {
        //1、 调用api根据id查询动态详情
       Movement movement = movementApi.findOneMovement(movementId);
       if (ObjectUtils.isEmpty(movement)){
           return null;
       }else {
           UserInfo userInfoApiById = userInfoApi.findById(movement.getUserId());
           return MovementsVo.init(userInfoApiById,movement);
       }
    }

    @DubboReference
    private VisitorsApi visitorsApi;
    /**
     * 我的首页-访客列表
     * @return
     */
    //首页-访客列表
    public List<VisitorsVo> queryVisitorsList() {
        //1、查询访问时间
        String key = Constants.VISITORS_USER;
        String hashKey = String.valueOf(UserHolder.getUserId());
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(value) ? null:Long.valueOf(value);
        //2、调用API查询数据列表 List<Visitors>
        List<Visitors> list =  visitorsApi.queryMyVisitors(date,UserHolder.getUserId());
        if(CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        //3、提取用户的id
        List<Long> userIds = CollUtil.getFieldValues(list, "visitorUserId", Long.class);
        //4、查看用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);
        //5、构造返回
        List<VisitorsVo> vos = new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            if(userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo, visitors);
                vos.add(vo);
            }
        }
        return vos;
    }
}
